package quartz.controller;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.*;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("batch")
public class BatchController {
    final JobLauncher jobLauncher;
    final JobRegistry jobRegistry;
    final JobExplorer jobExplorer;
    final JobOperator jobOperator;
    // final StepRegistry stepRegistry;
    final JobRepository jobRepository;

    @GetMapping("jobName")
    Object jobName() {
        // jobExplorer.getJobNames();
        return jobRegistry.getJobNames();
    }

    @GetMapping("stop")
    void stop(Long executionId) throws NoSuchJobExecutionException, JobExecutionNotRunningException {
        jobOperator.stop(executionId);
    }

    @GetMapping("abandon")
    void abandon(Long jobExecutionId) throws JobExecutionAlreadyRunningException, NoSuchJobExecutionException {
        jobOperator.abandon(jobExecutionId);
    }

    @GetMapping("start")
    void start(String jobName, String parameters) throws JobInstanceAlreadyExistsException, NoSuchJobException, JobParametersInvalidException {
        jobOperator.start(jobName, parameters);
    }

    @GetMapping("restart")
    void restart(Long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobException, NoSuchJobExecutionException, JobParametersInvalidException, JobRestartException {
        jobOperator.restart(executionId);
    }

    @GetMapping("startNextInstance")
    void startNextInstance(String jobName) throws JobInstanceAlreadyCompleteException, NoSuchJobException, JobExecutionAlreadyRunningException, JobParametersInvalidException, JobParametersNotFoundException, JobRestartException {
        jobOperator.startNextInstance(jobName);
    }

    @GetMapping("queryjob")
    Object queryjob() {
        List<Job> list = new LinkedList<>();
        for (String jobName : jobExplorer.getJobNames()) {
            for (JobInstance jobInstance : jobExplorer.getJobInstances(jobName, 0, Integer.MAX_VALUE)) {
                for (JobExecution jobExecution : jobExplorer.getJobExecutions(jobInstance)) {
                    Job j = new Job();
                    j.setJId(jobInstance.getId());
                    j.setIId(jobInstance.getInstanceId());
                    j.setEId(jobExecution.getId());
                    j.setName(jobName);
                    j.setStartTime(jobExecution.getStartTime());
                    j.setEndTime(jobExecution.getEndTime());
                    j.setStatus(jobExecution.getStatus().getBatchStatus().name());
                    j.setExitStatus(jobExecution.getExitStatus().getExitCode());
                    String param = jobExecution.getJobParameters().toString();
                    j.setParam(param.substring(1, param.length() - 1));
                    for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
                        stepExecution.getStepName();
                        stepExecution.getStatus();
                    }
                    list.add(j);
                }
            }
        }
        return list;
    }

    @Getter
    @Setter
    @ToString
    public static class Job {
        Long jId;
        Long iId;
        Long eId;
        String name;
        Date startTime;
        Date endTime;
        String status;
        String exitStatus;
        JobParameters jobParameters;
        String param;
    }
}